home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Utilities / InfoUtil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  60.1 KB  |  2,304 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        InfoUtil.cpp
  3.  
  4.     Contains:    implementation of Info getters & setters
  5.  
  6.     Owned by:    Doug Hill
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <24>     12/9/96    EL        1602726: Remove duplicate editor when part
  13.                                     cannot be loaded and is replaced by NoPart.
  14.         <23>     12/3/96    JP        1401371,1162540: Stop calling
  15.                                     SetProcessName & SetProcessIcon
  16.         <22>      11/19/96    EL        1602726: NoPart should not put up a editor
  17.                                     user string that is already in the menu.
  18.         <21>      10/10/96    TJ        Wrapped ProcessHack.
  19.         <20>      10/10/96    RA        1343748: Display editor user string in
  20.                                     PartInfo dlg for NoPart
  21.         <19>     10/7/96    RA        1343814: Use prefered kind string in SU for
  22.                                     NoPart
  23.         <18>     10/5/96    JP        1162540,1162541: Process name & icon calls
  24.         <17>     9/19/96    TJ        Made it compile with out PCH.
  25.         <16>     9/17/96    RA        1383945: ODRenamePartWindows should use
  26.                                     TempODWindowIterator,1363261:
  27.                                     ODGetIconFamily routines should reset
  28.                                     Desktop DB if Finder isn't running
  29.         <15>     9/13/96    EL        1376678: display meta character in menu
  30.                                     item. 1385235: activate menu item in Kind
  31.                                     menu if Kind is stored. 1383086: Only
  32.                                     update title of root windows.
  33.         <13>     7/10/96    EL        1366381: if there is no comment,
  34.                                     ODSetPOComments should delete comment
  35.                                     property.
  36.         <12>      7/8/96    EL        1364853: Add ODSetPartNameReturnError to do
  37.                                     set part name but get error code back.
  38.         <11>     6/24/96    RA        T10025: Wrapped obsoleted utils w/
  39.                                     _OD_IMPL_ ; they are not available to parts
  40.         <10>     6/19/96    EL        1348424: Deactivate file types that appears
  41.                                     in "kinds" popup
  42.          <9>     6/18/96    TJ        Don't use private ODPartWrapper class
  43.          <8>     6/12/96    RA        1301627, 1297102: ODGetIconFamily now looks
  44.                                     in all volume DTDB's , added StVolumeLoop;
  45.                                     ODGetPartName no longer crashes if window
  46.                                     isn't registered
  47.          <7>      6/5/96    EL        1355529: Move InitKindsPopUp from Info.cpp
  48.                                     to here for sharing, add parameters for
  49.                                     AddTypesToMenu to check for default data
  50.                                     kind.
  51.          <6>      6/4/96    EL        1279544: Move GetTypeListItem from
  52.                                     TransDlg.cpp to InfoUtil.cpp.
  53.          <5>     5/31/96    jpa        T10012: Added ODGetIconFilePlatformCreator.
  54.          <4>     5/28/96    EL        #1328903: slash and other meta characters
  55.                                     should be allowed in the kind popup menu.
  56.                                     #1348424: File Types should not appear in
  57.                                     kind popup menu.
  58.          <3>    .04.1996    NP        1330731: Don't use stationery property
  59.                                     anymore.
  60.          <2>     3/15/96    DH        1.0.2: OpenDoc: Drag of no-part to trash
  61.                                     rejected. Fixed
  62.                                     ODGetIconFilePlatformTypeFromPartSU so that
  63.                                     it has proper exception handling and a
  64.                                     default return value.
  65.  
  66.     To Do:
  67.     In Progress:
  68.     
  69. */
  70.  
  71. #ifndef _PLFMDEF_
  72. #include "PlfmDef.h"
  73. #endif
  74.  
  75. #ifndef _STDTYPIO_
  76. #include "StdTypIO.h"
  77. #endif
  78.  
  79. #ifndef _USERSRCM_
  80. #include "UseRsrcM.h"
  81. #endif
  82.  
  83. #ifndef _ODPROCESSUTILS_
  84. #include "ODProcessUtils.h"
  85. #endif
  86.  
  87. #ifndef SOM_ODSession_xh
  88. #include <ODSessn.xh>
  89. #endif
  90.  
  91. #ifndef SOM_ODDraft_xh
  92. #include <Draft.xh>
  93. #endif
  94.  
  95. #ifndef SOM_ODDocument_xh
  96. #include <Document.xh>
  97. #endif
  98.  
  99. #ifndef SOM_ODContainer_xh
  100. #include <ODCtr.xh>
  101. #endif
  102.  
  103. #ifndef SOM_ODWindowState_xh
  104. #include <WinStat.xh>
  105. #endif
  106.  
  107. #ifndef SOM_ODWindow_xh
  108. #include <Window.xh>
  109. #endif
  110.  
  111. #ifndef SOM_ODStorageUnit_xh
  112. #include <StorageU.xh>
  113. #endif
  114.  
  115. #ifndef SOM_Module_OpenDoc_StdProps_defined
  116. #include <StdProps.xh>
  117. #endif
  118.  
  119. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  120. #include <StdTypes.xh>
  121. #endif
  122.  
  123. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  124. #include <StdDefs.xh>
  125. #endif
  126.  
  127. #ifndef _ODUTILS_
  128. #include <ODUtils.h>
  129. #endif
  130.  
  131. #ifndef _DLOGUTIL_
  132. #include <DlogUtil.h>
  133. #endif
  134.  
  135. #ifndef SOM_ODFrame_xh
  136. #include <Frame.xh>
  137. #endif
  138.  
  139. #ifndef SOM_ODFacet_xh
  140. #include <Facet.xh>
  141. #endif
  142.  
  143. #ifndef SOM_ODPart_xh
  144. #include <Part.xh>
  145. #endif
  146.  
  147. #ifndef SOM_ODBinding_xh
  148. #include <ODBindng.xh>
  149. #endif
  150.  
  151. #ifndef SOM_ODStorageUnitView_xh
  152. #include <SUView.xh>
  153. #endif
  154.  
  155. #ifndef _PASCLSTR_
  156. #include "PasclStr.h"
  157. #endif
  158.  
  159. #ifndef _ODMEMORY_
  160. #include "ODMemory.h"
  161. #endif
  162.  
  163. #ifndef _PLFMFILE_
  164. #include <PlfmFile.h>
  165. #endif
  166.  
  167. #ifndef _ITEXT_
  168. #include <IText.h>
  169. #endif
  170.  
  171. #ifndef SOM_ODTypeList_xh
  172. #include <TypeList.xh>
  173. #endif
  174.  
  175. #ifndef SOM_ODTypeListIterator_xh
  176. #include <TypLsItr.xh>
  177. #endif
  178.  
  179. #ifndef _EXCEPT_
  180. #include "Except.h"
  181. #endif
  182.  
  183. #ifndef _BNDNSUTL_
  184. #include "BndNSUtl.h"
  185. #endif
  186.  
  187. #ifndef _TRANSUTL_
  188. #include <TransUtl.h>
  189. #endif
  190.  
  191. #ifdef __SC__
  192. #ifndef __PACKAGES__
  193. #include <Packages.h>
  194. #endif
  195. #else
  196. #ifndef __TEXTUTILS__
  197. #include <TextUtils.h>
  198. #endif
  199. #endif
  200.  
  201. #ifndef __STRING__
  202. #include <String.h>
  203. #endif
  204.  
  205. #ifndef __GESTALTEQU__
  206. #include <GestaltEqu.h>
  207. #endif
  208.  
  209. #ifndef __DIALOGS__
  210. #include <Dialogs.h>
  211. #endif
  212.  
  213. #ifndef __TOOLUTILS__
  214. #include <ToolUtils.h>
  215. #endif
  216.  
  217. #ifndef __FONTS__
  218. #include <Fonts.h>
  219. #endif
  220.  
  221. #ifndef __CONTROLS__
  222. #include <Controls.h>
  223. #endif
  224.  
  225. #ifndef __ICONS__
  226. #include <Icons.h>
  227. #endif
  228.  
  229. #ifndef __FINDER__
  230. #include <Finder.h>
  231. #endif
  232.  
  233. #ifndef _INFOUTIL_
  234. #include "InfoUtil.h"
  235. #endif
  236.  
  237. #ifndef SOM_ODTranslation_xh
  238. #include <Translt.xh>
  239. #endif
  240.  
  241. #ifndef _EDITRSET_
  242. #include "EditrSet.h"
  243. #endif
  244.  
  245. #ifndef _STORUTIL_
  246. #include <StorUtil.h>
  247. #endif
  248.  
  249. #ifndef _ISOSTR_
  250. #include "ISOStr.h"
  251. #endif
  252.  
  253. #ifndef SOM_ODWindowIterator_xh
  254. #include <WinIter.xh>
  255. #endif
  256.  
  257. #ifndef SOM_ODNameSpaceManager_xh
  258. #include <NmSpcMg.xh>
  259. #endif
  260.  
  261. #ifndef SOM_ODValueNameSpace_xh
  262. #include <ValueNS.xh>
  263. #endif
  264.  
  265. #ifndef SOM_ODStorageSystem_xh
  266. #include <ODStor.xh>
  267. #endif
  268.  
  269. #ifndef _NMSPCUTL_
  270. #include <NmSpcUtl.h>
  271. #endif
  272.  
  273. #ifndef _UTILDEFS_
  274. #include "UtilDefs.h"
  275. #endif
  276.  
  277. #ifndef _TEMPOBJ_
  278. #include <TempObj.h>
  279. #endif
  280.  
  281. #ifndef _TEMPITER_
  282. #include <TempIter.h>
  283. #endif
  284.  
  285. #ifndef _ORDCOLL_
  286. #include "OrdColl.h"
  287. #endif
  288.  
  289. #ifndef _STDTYPIO_
  290. #include <StdTypIO.h>
  291. #endif
  292.  
  293. #ifndef _DOCUTILS_
  294. #include "DocUtils.h"
  295. #endif
  296.  
  297. #pragma segment Info
  298.  
  299. //==============================================================================
  300. // Constants
  301. //==============================================================================
  302.  
  303. // this duplicate the definition from StorDef.h
  304. const    ODValueType    kODAppleFileTypePrefix    = "+//ISO 9070/ANSI::113722::US::CI LABS::MacOS:FileType:";
  305.  
  306. const short kControlInactive = 255;
  307. const short kControlActive = 0;
  308. #define SKIPOMPARSE
  309. #ifdef SKIPOMPARSE
  310. static const char* const kODIconFamilyBaseString = kODIconFamily ":";
  311. #else
  312. static const char* const kODIconFamilyBaseString = "^^^^correct def.^^^^^";
  313. #endif
  314. static const ResType            kIconType[6] = {'ICN#','icl4','icl8','ics#','ics4','ics8'};
  315. static const short                kIconSize[6] = {256,   512,   1024,  64,    128,   256   };
  316.  
  317. const ODPlatformType kODFileType_hfs = 0x68667320;    // 'hfs '
  318.  
  319. //==============================================================================
  320. // Static Function declarations
  321. //==============================================================================
  322.  
  323. ODTime    ODGetDateProperty(Environment* ev, 
  324.             ODStorageUnit* su,
  325.             ODPropertyName prop);
  326.  
  327. void    ODSetDateProperty(Environment* ev, 
  328.             ODStorageUnit* su,
  329.             ODPropertyName prop,
  330.             ODTime dateTime);
  331.  
  332. ODStatic ODBoolean         ODUserRenameFile(Environment* ev,
  333.                                 ODSession* session,
  334.                                 PlatformFile*    usersFile, 
  335.                                 ODIText* name,
  336.                                 DescType replaceOption);
  337. // If PlatformFile is made a shared utility, then the above function should probably be
  338. // integrated into the PlatformFile::Rename method.
  339.  
  340. ODStatic ODIconFamily    GetGenericIcon( short iconID );
  341.  
  342. ODStatic OSErr             DetachIconProc( ResType, Handle *theIcon, void */*yourDataPtr*/ );
  343.  
  344. ODStatic ODBoolean        CommentsDontMatch(ODIText* dtComments, ODIText* propComments);
  345.  
  346. //==============================================================================
  347. // Info functions
  348. //==============================================================================
  349.  
  350.  
  351. ODStorageUnit* ODGetSUFromPstObj(Environment* ev, ODPersistentObject* pstobj)
  352. {
  353.     return pstobj->GetStorageUnit(ev);
  354. }
  355.  
  356. //-------------------------------------------------------------------------------------
  357. // Part & Frame Property getters and setters
  358. //-------------------------------------------------------------------------------------
  359.  
  360. ODIText*
  361. ODGetPOComments(Environment* ev, ODPart *part, ODIText* comments)
  362. {
  363.     ODStorageUnit*    su = ODGetSUFromPstObj(ev, part);
  364.     ODIText*        propComments;
  365.  
  366.     propComments = ODGetITextProp(ev, su, kODPropComments, kODMacIText, comments);
  367.     return propComments;
  368. }
  369.  
  370. void    ODSetPOComments(Environment* ev, ODPart *part, ODIText* comments)
  371. {
  372.     ODStorageUnit*    su = ODGetSUFromPstObj(ev, part);
  373.     
  374.     if (comments)
  375.         ODSetITextProp(ev, su, kODPropComments, kODMacIText, comments);
  376.     else {
  377.         if ( ODSUExistsThenFocus(ev, su, kODPropComments, kODMacIText) )
  378.             su->Remove(ev);
  379.         if ( ODSUExistsThenFocus(ev, su, kODPropComments, kODIntlText) )
  380.             su->Remove(ev);
  381.     }
  382. }
  383.  
  384.  
  385. ODIText*
  386. ODGetComments(Environment* ev, ODFrame* frame, ODIText* comments)
  387. {
  388.     TempODPart        part = frame->AcquirePart(ev);
  389.     ODIText*        propComments;
  390.     ODIText*        dtComments;
  391.  
  392.     propComments = ODGetPOComments(ev, part, comments);
  393.     if (comments && !propComments)
  394.         propComments = comments;
  395.     TempPlatformFile usersFile = ODGetFileIfRoot(ev, frame);
  396.     if (usersFile)
  397.     {
  398.         dtComments = usersFile->GetComments();
  399.         if (!dtComments || GetITextStringLength(dtComments) == 0)
  400.         {
  401.             // since there are no desktop comments
  402.             // make the desktop comments match the property
  403.             usersFile->SetComments(propComments);
  404.         }
  405.         else if (CommentsDontMatch(dtComments, propComments) && dtComments)
  406.         {
  407.             // if there are desktop comments and the property comments don't match
  408.             // then the desktop comments take precedence, so return the desktop comments
  409.             DisposeIText(propComments);
  410.             propComments = dtComments;
  411.             dtComments = kODNULL;
  412.         }
  413.         DisposeIText(dtComments);
  414.     }
  415.     return propComments;
  416. }
  417.  
  418. void    ODSetComments(Environment* ev, ODFrame* frame, ODIText* comments)
  419. {
  420.     TempODPart        part = frame->AcquirePart(ev);
  421.     ODSetPOComments(ev, part, comments);
  422.     TempPlatformFile usersFile = ODGetFileIfRoot(ev, frame);
  423.     if (usersFile)
  424.         usersFile->SetComments(comments);
  425. }
  426.  
  427.  
  428. ODULong    ODGetPOSize(Environment* ev, ODPersistentObject* pstobj)
  429. {
  430.     ODStorageUnit* su = ODGetSUFromPstObj(ev, pstobj);
  431.     su->Focus(ev, kODNULL, kODPosAll, kODNULL,0, kODPosAll);
  432.     return su->GetSize(ev);
  433. }
  434.  
  435. ODID ODGetPOID(Environment* ev, ODPersistentObject* pstobj)
  436. {
  437.     ODStorageUnit* su = ODGetSUFromPstObj(ev, pstobj);
  438.     su->Focus(ev, kODNULL, kODPosAll, kODNULL,0, kODPosAll);
  439.     return su->GetID(ev);
  440. }
  441.  
  442. ODTime    ODGetDateProperty(Environment* ev, 
  443.             ODStorageUnit* su,
  444.             ODPropertyName prop)
  445. {    return ODGetTime_TProp(ev, su, prop, kODTime_T);}
  446.  
  447. void    ODSetDateProperty(Environment* ev, 
  448.             ODStorageUnit* su,
  449.             ODPropertyName prop,
  450.             ODTime dateTime)
  451. {    ODSetTime_TProp(ev, su, prop, kODTime_T, dateTime);}
  452.  
  453.  
  454. ODULong    ODGetCreationDate(Environment* ev, 
  455.                 ODStorageUnit* su)
  456. {    return ODGetDateProperty(ev, su, kODPropCreateDate);}
  457.  
  458. void    ODSetCreationDate(Environment* ev, 
  459.                 ODStorageUnit* su,
  460.                 ODTime dateTime)
  461. {    ODSetDateProperty(ev, su, kODPropCreateDate, dateTime);}
  462.  
  463.  
  464. ODULong    ODGetModificationDate(Environment* ev, 
  465.                 ODStorageUnit* su)
  466. {    return ODGetDateProperty(ev, su, kODPropModDate);}
  467.  
  468. void    ODSetModificationDate(Environment* ev, 
  469.                 ODStorageUnit* su,
  470.                 ODTime dateTime)
  471. {    ODSetDateProperty(ev, su, kODPropModDate, dateTime);}
  472.  
  473.  
  474. ODIText*    ODGetModifiedBy(Environment* ev, 
  475.                 ODStorageUnit* su, ODIText* userName)
  476. {
  477.     return ODGetITextProp(ev, su, kODPropModUser,
  478.             kODMacIText, userName);
  479. }
  480.  
  481. void        ODSetModifiedBy(Environment* ev, 
  482.                 ODStorageUnit* su, ODIText* userName)
  483. {
  484.     ODSetITextProp(ev, su, kODPropModUser,
  485.             kODMacIText, userName);
  486. }
  487.  
  488.  
  489. //-------------------------------------------------------------------------------------
  490. // Part only Property getters and setters
  491. //-------------------------------------------------------------------------------------
  492. ODIText*    ODGetPartName(Environment* ev, 
  493.                 ODFrame* frame, ODIText* name)
  494. {
  495.     TempODPart part = frame->AcquirePart(ev);
  496.     TempODIText partName = ODGetPOName(ev, part, name);
  497.     
  498.     TempPlatformFile usersFile = ODGetFileIfRoot(ev, frame);
  499.     if (usersFile)
  500.     {
  501.         TempODIText fileName = usersFile->GetName();
  502.         if ( CommentsDontMatch( fileName, partName ) )
  503.             return CopyIText( fileName );
  504.     }
  505.     return CopyIText( partName );
  506. }
  507.  
  508. ODError    ODSetPartNameReturnError(Environment* ev, 
  509.                 ODFrame* frame, ODIText* name, DescType replaceOption)
  510.         // Renames the part of the frame passed in.
  511.         // If there is any error return the error.
  512.         // The frame helps more easily determine whether
  513.         // the part is the root part of the document or not.
  514.         // For example, renaming the root part of the document could fail
  515.         // if there was a file with the same name and the user canceled the
  516.         // "Replace?" dialog.
  517. {
  518.     ASSERT(frame != kODNULL, kODErrIllegalNullInput);
  519.     
  520.     TempODPart part = frame->AcquirePart(ev);
  521.     TempODWindow window = frame->AcquireWindow(ev);
  522.                 
  523.     ODFrame*     contFrame = frame->AcquireContainingFrame(ev);
  524.     ODBoolean     isRootPart = (contFrame == kODNULL);
  525.     ODReleaseObject(ev, contFrame);
  526.     
  527.     ODBoolean    isRootPartOfDocument = isRootPart && window->IsRootWindow(ev);
  528.     
  529.     ODName*        oldName = kODNULL; ODVolatile(oldName);
  530.     PlatformFile*    usersFile = kODNULL; ODVolatile(usersFile);
  531.     ODError        error = noErr;
  532.  
  533.     TRY
  534.         ODStorageUnit*    partSU    = ODGetSUFromPstObj(ev, part);
  535.         ODSession*        session = partSU->GetSession(ev);
  536.         oldName = ODGetPartName(ev, frame, kODNULL); 
  537.  
  538.         if (isRootPartOfDocument)
  539.         {
  540.             ODDraft*        draft = partSU->GetDraft(ev);
  541.             usersFile = 
  542.                 GetPlatformFileFromContainer(ev, draft->GetDocument(ev)->GetContainer(ev));
  543.  
  544.             if (ODUserRenameFile(ev, session, usersFile, name, replaceOption))
  545.             {
  546.                 ODWindowState* windowState = session->GetWindowState(ev);
  547.                 windowState->SetDefaultWindowTitles(ev, draft);
  548.                 ODSetPOName(ev, part, name);
  549.                 ODRenamePartWindows(ev,session,part,oldName,name);
  550.                 if (isRootPart)
  551.                 {
  552.                     Str255 pName;
  553.                     GetITextPString(name, pName);
  554.                     SetWTitle(window->GetPlatformWindow(ev), pName);
  555.                 }
  556.             }
  557.         }
  558.         else
  559.         {
  560.             ODSetPOName(ev, part,name);
  561.             ODRenamePartWindows(ev,session,part,oldName,name);
  562.         }
  563.         
  564.     CATCH_ALL
  565.         error = ErrorCode();
  566. #if ODDebug
  567.         if (error != userCanceledErr)
  568.             WARN("ODSetPartName failed, error %ld",error);
  569. #endif
  570.     ENDTRY
  571.  
  572.     ODDeleteObject(usersFile);
  573.     DisposeIText(oldName);
  574.     
  575.     return error;
  576. }
  577.  
  578. ODBoolean    ODSetPartName(Environment* ev, 
  579.                 ODFrame* frame, ODIText* name, DescType replaceOption)
  580.         // Renames the part of the frame passed in.
  581.         // Returns whether or not it succeeded.
  582.         // Just call ODSetPartNameReportError and return false if there is error
  583. {
  584.     return (ODSetPartNameReturnError(ev, frame, name, replaceOption) == noErr);
  585. }
  586.  
  587. void
  588. ODRenamePartWindows( Environment *ev, ODSession *session,
  589.                      ODPart *part, ODIText *oldName, ODIText *name )
  590. {
  591.     // go through all windows which have this part as their root, and
  592.     // have the current name of the part as a prefix
  593.     // rename their prefix to be the new name
  594.     Str255    pOldName;
  595.     Str255    pNewName;
  596.     Str255    pWinTitle;
  597.     ODUByte pOldNameLen;
  598.     ODUByte pNewNameLen;
  599.     
  600.     GetITextPString(oldName, pOldName);
  601.     pOldNameLen = pOldName[0];
  602.     GetITextPString(name, pNewName);
  603.     pNewNameLen = pNewName[0];
  604.     
  605.     TempODWindowIterator iter(ev,session->GetWindowState(ev));
  606.     for (ODWindow* window = iter.First(); 
  607.          iter.IsNotComplete();
  608.          window = iter.Next())
  609.     {
  610.         if (window->IsRootWindow(ev))
  611.         {
  612.             TempODPart winPart = window->GetRootFrame(ev)->AcquirePart(ev);
  613.             if (ODObjectsAreEqual(ev, part, winPart))
  614.             {
  615.                 // Check to see if name of window has pOldName as prefix
  616.                 ODPlatformWindow pwindow = window->GetPlatformWindow(ev);
  617.                 GetWTitle(pwindow, pWinTitle);
  618.                 if (pOldNameLen && (pOldNameLen >= pWinTitle[0]) && 
  619.                         !strncmp((char*)&pWinTitle[1], (char*)&pOldName[1], pOldNameLen) &&
  620.                         !EqualPascalStrings(pWinTitle, pNewName))
  621.                 {
  622.                     ODUByte suffixLen = pWinTitle[0] - pOldNameLen;
  623.                     if (suffixLen + pNewNameLen > 255) 
  624.                         suffixLen = 255 - pNewNameLen;
  625.                     strncpy((char*)&pNewName[pNewNameLen+1], 
  626.                             (char*)&pWinTitle[pOldNameLen+1],
  627.                             suffixLen);
  628.                     pNewName[0] = pNewNameLen+suffixLen;
  629.                     SetWTitle(pwindow, pNewName);
  630.                 }
  631.             }
  632.         }
  633.     }
  634. }
  635.  
  636.  
  637. ODIText*    ODGetPOName(Environment* ev, ODPersistentObject* pstobj,ODIText* name)
  638. {
  639.     return ODGetITextProp(ev, ODGetSUFromPstObj(ev, pstobj), kODPropName, kODMacIText,name);
  640. }
  641.  
  642. void        ODSetPOName(Environment* ev, ODPersistentObject* pstobj,ODIText* name)
  643. {
  644.     ODSetITextProp(ev, ODGetSUFromPstObj(ev, pstobj), kODPropName, kODMacIText, name);
  645. }
  646.  
  647. void        ODSetPONameUsingSU(Environment* ev, ODStorageUnit* su, ODIText* name)
  648. {
  649.     ODSetITextProp(ev, su, kODPropName, kODMacIText, name);
  650. }
  651.  
  652. ODName*    ODGetCategory(Environment* ev, ODPart* part, ODNameSpaceManager* nsm)
  653. {
  654.     return ODGetCatFromPartSU(ev, ODGetSUFromPstObj(ev, part), nsm);
  655. }
  656.  
  657. ODName*    ODGetCatFromPartSU(Environment* ev, ODStorageUnit* su, ODNameSpaceManager* nsm)
  658. {
  659.     ODType kind = ODGetKindFromPartSU(ev, su);
  660.     ODName*    categoryName = ODGetCatFromKind(ev, kind, nsm);
  661.     ODDisposePtr( kind );
  662.  
  663.     return categoryName;
  664. }
  665.  
  666. #ifdef _OD_IMPL_
  667. ODName*    ODGetCatFromKind(Environment* ev, ODType kind, ODNameSpaceManager* nsm)
  668. {
  669.     StringHandle strHandle = 0;
  670.     ODTypeList* categoryList = GetCategoriesOfKind(nsm, kind);
  671.     ODTypeListIterator* catIter = kODNULL;
  672.     ODType category = kODNULL;
  673.     ODName*    categoryName = kODNULL;
  674.     
  675.     if (categoryList)
  676.     {
  677.         catIter = categoryList->CreateTypeListIterator(ev);
  678.         category = catIter->First(ev);
  679.         ODDeleteObject(catIter);
  680.     }
  681.     
  682.     if (category == kODNULL || !GetUserCatFromCat(nsm, category, &categoryName)) {
  683.         CUsingLibraryResources r;
  684.         categoryName = GetODIText(kODPartInfoStrUnknownID);
  685.     }
  686.     //else // make a disposable copy // NO NEED TO! GetUserCatFromCat returns a copy!
  687.     //    categoryName = CopyIText(categoryName);
  688.         
  689.     ODDisposePtr(category);
  690.  
  691.     return categoryName;
  692. }
  693. #endif
  694.  
  695. ODType    ODGetKindFromPartSU(Environment* ev, ODStorageUnit* su)
  696. {
  697.     ODULong unused;
  698.     ODType kind = ODGetISOStrProp(ev, su, kODPropPreferredKind, kODISOStr, kODNULL, &unused);
  699.     if ( kind == kODNULL )
  700.         if ( su->Exists(ev, kODPropContents, (ODValueType) kODNULL,1) )
  701.         {
  702.             su->Focus(ev, kODPropContents, kODPosSame, (ODValueType) kODNULL,1, kODPosSame);
  703.             kind = su->GetType(ev);
  704.  
  705.             ODTranslation* translation = su->GetSession(ev)->GetTranslation(ev);
  706.             TempODType hfsType = 
  707.                 translation->GetISOTypeFromPlatformType(ev, kODFileType_hfs, kODPlatformDataType);
  708.  
  709.             if ( ODISOStrEqual(kind, hfsType) )
  710.             {
  711.                 ODDisposePtr(kind);
  712.                 kind = kODNULL;
  713.                 if ( su->Exists(ev, kODPropContents, (ODValueType) kODNULL,2) )
  714.                 {
  715.                     su->Focus(ev, kODPropContents, kODPosSame, (ODValueType) kODNULL,2, kODPosSame);
  716.                     kind = su->GetType(ev);
  717.                 }
  718.             }
  719.         }
  720.     return kind;
  721. }
  722.  
  723. ODType    ODGetKind(Environment* ev, ODPart* part)
  724. {
  725.     return ODGetKindFromPartSU(ev, ODGetSUFromPstObj(ev, part));
  726. }
  727.  
  728. ODPlatformType ODGetIconFilePlatformTypeFromPartSU(Environment* ev, ODStorageUnit* su)
  729. {
  730.     ODType partKind = kODNULL;
  731.     ODPlatformType partOSType;
  732.     ODVolatile(partKind);
  733.     ODVolatile(partOSType);
  734.     
  735.     TRY
  736.         ODSession* session = su->GetSession(ev);
  737.     
  738.         partKind = ODGetKindFromPartSU(ev, su);
  739.         partOSType = session->GetTranslation(ev)->
  740.                                 GetPlatformTypeFromISOType(ev, partKind);
  741.         if (partOSType != kODNULL)
  742.         {
  743.             ((ODUByte*)(&partOSType))[0] = kODPlatformKindFileChar1;
  744.         }
  745.         else
  746.         {
  747.             ODBoolean    partOSTypeFound = kODFalse;
  748.             ODValueNameSpace*    osTypeNameSpace = (ODValueNameSpace*)
  749.                 (session->GetNameSpaceManager(ev)->HasNameSpace(ev, kODKindOldMacOSType));
  750.         
  751.             if (osTypeNameSpace)
  752.             {
  753.                 ODPlatformType* typePtr;
  754.                 ODULong        unusedLength;
  755.                 partOSTypeFound = ValueNameSpaceGetEntry(osTypeNameSpace, 
  756.                                                         ev, partKind, 
  757.                                                         (ODPtr*) &typePtr, 
  758.                                                         &unusedLength);
  759.                 if (partOSTypeFound)
  760.                 {
  761.                     partOSType = *typePtr;
  762.                     ODDeleteObject( typePtr );
  763.                 }
  764.             }
  765.             if (!partOSTypeFound)
  766.                 partOSType = kODShellSignature;
  767.         }
  768.         
  769.         ODDisposePtr(partKind);
  770.     CATCH_ALL
  771.         ODDisposePtr(partKind);
  772.         partOSType = kODShellSignature;
  773.     ENDTRY
  774.  
  775.     return partOSType;
  776. }
  777.  
  778.  
  779. static ODPlatformType
  780. LookupEditorCreator( Environment *ev, ODSession *session, ODEditor editor )
  781. {
  782.     ODPlatformType creator = kODShellSignature;
  783.     
  784.     if( editor ) {
  785.         ODNameSpaceManager *nsm = session->GetNameSpaceManager(ev);
  786.         ODValueNameSpace *ns = (ODValueNameSpace*)
  787.                                 nsm->HasNameSpace(ev, kODEditorPlatformSignature);
  788.         if (ns) {
  789.             ODPlatformType* typePtr;
  790.             ODULong        unusedLength;
  791.             if( ValueNameSpaceGetEntry(ns, ev, editor,  (ODPtr*) &typePtr, &unusedLength) ) {
  792.                 creator = *typePtr;
  793.                 ODDeleteObject( typePtr );
  794.             }
  795.         }
  796.     }
  797.     return creator;
  798. }
  799.  
  800.  
  801. ODPlatformType ODGetIconFilePlatformCreatorFromPartSU( Environment *ev, ODStorageUnit *su )
  802. {
  803.     // Ask Binding which editor will be used for this storage unit:
  804.     TempODISOStr editor = ODGetSession(ev,su)->GetBinding(ev)
  805.                                 ->ChooseEditorForPart(ev,su,kODNULL);
  806.     return LookupEditorCreator(ev, ODGetSession(ev,su), editor);
  807. }
  808.  
  809.  
  810. ODPlatformType ODGetIconFilePlatformCreator( Environment *ev, ODPart *part )
  811. {
  812.     return LookupEditorCreator( ev, ODGetSession(ev,part),
  813.                                 part->GetRealPart(ev)->somGetClassName() );
  814. }
  815.  
  816.  
  817. //--------------------------------------------------------------------
  818. // ODGetPOIconFamily
  819. //--------------------------------------------------------------------
  820.  
  821. ODIconFamily
  822. ODGetPOIconFamily(Environment* ev, ODPart* part)
  823. {
  824.     //// FIRST, get the Mac icon value if one exists:
  825.     ODStorageUnit*    su = ODGetSUFromPstObj(ev, part);
  826.     ODIconFamily icons = ODGetIconFamilyProp(ev, su, 
  827.                                 kODPropCustomIcon, kODIconFamily, kAllIconsMask);
  828.     if (icons )
  829.         return icons;
  830.         
  831.     //// OTHERWISE, look for other platform icon values:
  832.     if (ODSUExistsThenFocus(ev,su, kODPropCustomIcon, kODNULL))
  833.     {
  834.         ODULong numValues = su->CountValues(ev);
  835.         for( ODULong i = 1; i <= numValues; i++ )
  836.         {
  837.             su->Focus(ev, kODNULL, kODPosSame, kODNULL, 0, kODPosNextSib);    // Next value
  838.             TempODValueType type = su->GetType(ev);
  839.             if( strncmp(type,kODIconFamilyBaseString,strlen(kODIconFamilyBaseString)) == 0 )
  840.             {
  841.                 // This value is an icon family for some platform. Use the b/w icons
  842.                 // because we don't know what color table the color ones may use.
  843.                 icons = ODGetIconFamilyProp(ev, su, kODPropCustomIcon, type, kBWIconsMask);
  844.                 if( icons )
  845.                     return icons;
  846.             }
  847.         }
  848.         return kODNULL;
  849.     }
  850.     return icons;
  851. }
  852.  
  853.  
  854.  
  855. //--------------------------------------------------------------------
  856. // ODSetPOIconFamily
  857. //--------------------------------------------------------------------
  858.  
  859. void    ODSetPOIconFamily(Environment* ev, ODPart* part, 
  860.             ODIconFamily icons, ODBoolean deleteOtherPlatformIcons)
  861. {
  862.     ODSetIconFamilyProp(ev, ODGetSUFromPstObj(ev, part), 
  863.                                 kODPropCustomIcon, kODIconFamily,
  864.                                 icons, deleteOtherPlatformIcons);
  865. }
  866.  
  867. //==============================================================================
  868. //    StVolumeLoop
  869. //==============================================================================
  870.  
  871. //——————————————————————————————————————————————————————————————————————————————
  872. //    StVolumeLoop::StVolumeLoop
  873. //——————————————————————————————————————————————————————————————————————————————
  874.  
  875. const short kSystemVolumeID = -1;    // -1 is the refnum of the System Volume.
  876.  
  877. //——————————————————————————————————————————————————————————————————————————————
  878. //    StVolumeLoop::StVolumeLoop
  879. //——————————————————————————————————————————————————————————————————————————————
  880.  
  881. StVolumeLoop::StVolumeLoop()
  882. {
  883.     mInitialVRefNum    = kSystemVolumeID;
  884.     
  885.     mVolumePass        = kInitialPass;
  886.     mVolumeIndex    = 0;
  887. }
  888.  
  889. //——————————————————————————————————————————————————————————————————————————————
  890. //    StVolumeLoop::StVolumeLoop
  891. //——————————————————————————————————————————————————————————————————————————————
  892.  
  893. StVolumeLoop::StVolumeLoop(short inInitialVolume)
  894. {
  895.     mInitialVRefNum    = inInitialVolume;
  896.     
  897.     mVolumePass        = kInitialPass;
  898.     mVolumeIndex    = 0;
  899. }
  900.  
  901. //——————————————————————————————————————————————————————————————————————————————
  902. //    StVolumeLoop::NextVolume
  903. //——————————————————————————————————————————————————————————————————————————————
  904. Boolean 
  905. StVolumeLoop::NextVolume(short& outVolume) 
  906. {
  907.     Boolean foundVolumeToReturn = false;
  908.  
  909.     do
  910.     {
  911.         if (mVolumePass == kInitialPass)
  912.         {
  913.             // if we're on the initial pass (kInitialPass) just use
  914.             // the vRefNum of the initial volume itself.
  915.             
  916.         //    desktopParams.ioVRefNum = initialVRefNum;
  917.             outVolume = mInitialVRefNum;
  918.             foundVolumeToReturn = true;
  919.             
  920.             SetupNextVolumePass();
  921.         }
  922.         else
  923.         {
  924.             // Find the vRefNum of the next volume appropriate for this pass.
  925.             
  926.             mVolumeIndex++;
  927.             
  928.             // Convert the volumeIndex into a vRefNum.
  929.             
  930.             HParamBlockRec hfsParams;
  931.             hfsParams.volumeParam.ioNamePtr = nil;
  932.             hfsParams.volumeParam.ioVRefNum = 0;
  933.             hfsParams.volumeParam.ioVolIndex = mVolumeIndex;
  934.             OSErr error = ::PBHGetVInfoSync(&hfsParams);
  935.             
  936.             // A nsvErr indicates that the current pass is over.
  937.             
  938.             if (error != nsvErr)
  939.                 THROW_IF_ERROR(error);
  940.             
  941.             if (error == nsvErr)
  942.             {
  943.                 SetupNextVolumePass();
  944.             }
  945.             else if (hfsParams.volumeParam.ioVRefNum == mInitialVRefNum)
  946.             {
  947.                 // Since we handled the document volume during the initialPass,
  948.                 // skip it if we have hit that volume again.
  949.             
  950.                 // Don’t do anything, just let it continue to the next volume.
  951.             }
  952.             else if (IsRemoteVolume(hfsParams) != (mVolumePass == kRemotePass)) 
  953.             {
  954.                 // The current volume should be ignored by this pass because
  955.                 // it's not of the right type.
  956.                 
  957.                 // Don’t do anything, just let it continue to the next volume.
  958.             }
  959.             else
  960.             {
  961.                 // Okay, now we’ve found the vRefNum to return.
  962.  
  963.         //        desktopParams.ioVRefNum = hfsParams.volumeParam.ioVRefNum;
  964.                 outVolume = hfsParams.volumeParam.ioVRefNum;
  965.                 foundVolumeToReturn = true;
  966.             }
  967.         }
  968.         
  969.         // ••• This is where we return the correct volume ref.
  970.     }
  971.     while (!foundVolumeToReturn && mVolumePass != kDonePass);
  972.     
  973.     return mVolumePass != kDonePass;
  974. }
  975.  
  976. //——————————————————————————————————————————————————————————————————————————————
  977. //    StVolumeLoop::SetupNextVolumePass
  978. //——————————————————————————————————————————————————————————————————————————————
  979. void
  980. StVolumeLoop::SetupNextVolumePass()
  981. {
  982.     mVolumePass  = (EPass) ((short) mVolumePass + 1);
  983.     mVolumeIndex = 0;
  984. }
  985.  
  986. //——————————————————————————————————————————————————————————————————————————————
  987. //    StVolumeLoop::IsRemoteVolume
  988. //——————————————————————————————————————————————————————————————————————————————
  989. Boolean
  990. StVolumeLoop::IsRemoteVolume(HParamBlockRec& inHFSParams)
  991. {
  992.     // Call GetVolParms to determine if this volume is a server
  993.     // (a remote volume).
  994.     
  995.     GetVolParmsInfoBuffer volumeInfoBuffer;
  996.  
  997.     inHFSParams.ioParam.ioBuffer    = (Ptr) &volumeInfoBuffer;
  998.     inHFSParams.ioParam.ioReqCount    = sizeof(GetVolParmsInfoBuffer);
  999.     THROW_IF_ERROR(::PBHGetVolParmsSync(&inHFSParams));
  1000.     
  1001.     inHFSParams.ioParam.ioBuffer    = NULL;    // Make sure it's not pointing to
  1002.                                             // the stack anymore.
  1003.     
  1004.     // If the vMServerAdr field of the volume information buffer
  1005.     // is zero, this is a local volume.
  1006.     
  1007.     return (volumeInfoBuffer.vMServerAdr != 0);
  1008. }
  1009. //==============================================================================
  1010.  
  1011. //--------------------------------------------------------------------
  1012. // ODGetIconFamily
  1013. //
  1014. // Returns an ODIconFamily for the frames part or generic icons
  1015. // if an associated ODIconFamily is not found. Throws only if it can't
  1016. // get the generic icons.
  1017. //--------------------------------------------------------------------
  1018. ODIconFamily
  1019. ODGetIconFamily(Environment* ev, ODFrame* frame)
  1020. {
  1021.     ODIconFamily        r             = kODNULL; ODVolatile(r);
  1022.     TempPlatformFile     usersFile    = kODNULL; ODVolatile(usersFile);
  1023.     
  1024.     ASSERT_NOT_NULL(frame);
  1025.     
  1026.     TRY
  1027.     {
  1028.         usersFile = ODGetFileIfRoot(ev, frame);
  1029.     }
  1030.     CATCH_ALL
  1031.         //Thanks for sharing, but I can still continue my search, so I will.
  1032.     ENDTRY
  1033.     
  1034.     // First search phase, get custom icon family or look in the storage unit
  1035.     if (usersFile)
  1036.     {
  1037.         TRY
  1038.         {
  1039.             r = usersFile->GetCustomIconFamily();
  1040.         }
  1041.         CATCH_ALL
  1042.             //Thanks for sharing, but I can still continue my search, so I will.
  1043.         ENDTRY
  1044.     }
  1045.     else
  1046.     {
  1047.         TRY
  1048.         {
  1049.             TempODPart    part = kODNULL;
  1050.             part = frame->AcquirePart(ev);
  1051.             r = ODGetPOIconFamily(ev, part);
  1052.             // TempODPart is released here &/or on exception
  1053.         }
  1054.         CATCH_ALL
  1055.         ENDTRY
  1056.     }
  1057.     
  1058.     // Second search phase, search the available desktop databases
  1059.     if (r == kODNULL)
  1060.     {
  1061.         TRY
  1062.         {
  1063.             ODPlatformType kInvalidFileType = '\0\0\0\0';
  1064.             ODPlatformType fileType = kInvalidFileType; ODVolatile(fileType);
  1065.             ODPlatformType fileCreator = kODShellSignature;
  1066.  
  1067.             TRY
  1068.             {
  1069.                 TempODPart    part = kODNULL;
  1070.                 ODStorageUnit*    su = kODNULL;
  1071.                 part = frame->AcquirePart(ev);
  1072.                 su = ODGetSUFromPstObj(ev, CAST(part,ODPart));
  1073.                 ASSERT_NOT_NULL(su);
  1074.                 fileType = ODGetIconFilePlatformTypeFromPartSU(ev, su);
  1075.                 // TempODPart is released here &/or on exception
  1076.             }
  1077.             CATCH_ALL
  1078.             ENDTRY
  1079.             
  1080.             // Ask the desktop database by filetype for suite
  1081.             if (fileType != kInvalidFileType)
  1082.                 r = ODGetIconSuiteFromDesktopDB(fileType,fileCreator);
  1083.         }
  1084.         CATCH_ALL
  1085.         ENDTRY
  1086.     }
  1087.  
  1088.     // Final search phase, use generic icons as last resort
  1089.     if (r == kODNULL)
  1090.     {
  1091.         ODBoolean isStationery = kODFalse;
  1092.         ODSShort id = 0;
  1093.         
  1094.         TRY
  1095.         {
  1096.             isStationery = ODGetIsStationery(ev, frame);
  1097.         }
  1098.         CATCH_ALL
  1099.         ENDTRY
  1100.         
  1101.         if (isStationery)
  1102.         {
  1103.             id = genericStationeryIconResource;
  1104.         }
  1105.         else
  1106.         {
  1107.             id = genericDocumentIconResource;
  1108.         }
  1109.         
  1110.         TRY
  1111.         {
  1112.             r = GetGenericIcon(id);
  1113.         }
  1114.         CATCH_ALL
  1115.             RERAISE;
  1116.         ENDTRY
  1117.     }
  1118.     
  1119.     return r;
  1120. }
  1121.  
  1122. // Allocates an IconSuite if found and returns a ptr to it.
  1123. ODIconFamily ODGetIconSuiteFromDesktopDB(ODPlatformType fileType,ODPlatformType fileCreator)
  1124. {
  1125.     ODIconFamily    r             = kODNULL; ODVolatile(r);
  1126.     StVolumeLoop     volumeLoop;
  1127.     short             theVolume;
  1128.  
  1129.     TRY
  1130.     {
  1131.         while (!r && volumeLoop.NextVolume(theVolume))
  1132.         {
  1133.             OSErr err = noErr;
  1134.             DTPBRec pb;
  1135.             memset(&pb,'\0',sizeof(DTPBRec));
  1136.             pb.ioNamePtr = kODNULL;
  1137.             pb.ioVRefNum = theVolume; // index
  1138.             err = ::PBDTGetPath( &pb );
  1139.                         
  1140.             if (err == noErr)
  1141.             {
  1142.                 short DTRefNum = pb.ioDTRefNum; ODVolatile(DTRefNum);
  1143.                 
  1144.                 TRY
  1145.                 {
  1146.                     r = BuildIconSuiteFromDesktop(DTRefNum,fileType,fileCreator);
  1147.                 }
  1148.                 CATCH_ALL
  1149.                 ENDTRY
  1150.             }
  1151.             else if (err == desktopDamagedErr)
  1152.             {
  1153.                 /* if (!Finder) ::PBDTReset();
  1154.                 See Inside Macintosh: More Macintosh Toolbox ,  page 9-25 */
  1155.                 
  1156. #define kSystemType    'FNDR'
  1157. #define kFinderSig    'MACS'
  1158.  
  1159.                 ProcessSerialNumber theFinder;
  1160.                 OSErr err = FindProcess(&theFinder, kFinderSig,kSystemType);
  1161.                 
  1162.                 if (err)
  1163.                 {
  1164.                     WARN("The desktop database is damaged! Calling PBDTReset!");
  1165.                     
  1166.                     short DTRefNum = pb.ioDTRefNum;
  1167.                     OSErr err = noErr;
  1168.                     DTPBRec pb2;
  1169.                     memset(&pb2,'\0',sizeof(DTPBRec));
  1170.                     pb2.ioDTRefNum = DTRefNum;
  1171.                     err = ::PBDTResetSync( &pb2 );
  1172.                     
  1173.                     // if (err) there is nothing we or the caller can do, so just go on...
  1174.                     // We may have better luck w/ the next volume.
  1175.                 }
  1176.                 
  1177.             }
  1178.             // if there is a PBDTGetPath() error we ignore it and continue to next volume
  1179.         }
  1180.     }
  1181.     CATCH_ALL
  1182.         // if volume iterator dies, we can't get icons...
  1183.     ENDTRY
  1184.     
  1185.     return r;
  1186. }
  1187.  
  1188. ODIconFamily BuildIconSuiteFromDesktop(short DTRefNum,ODPlatformType fileType,ODPlatformType fileCreator)
  1189. {
  1190.     ODIconFamily icons = kODNULL; ODVolatile(icons);
  1191.     char iconBuffer[kLarge8BitIconSize]; // make room for largest possible icon bitmap
  1192.     const ODBoolean kDisposeHandlesInIconSuite = kODTrue;
  1193.     
  1194.     THROW_IF_ERROR( NewIconSuite(&icons) );
  1195.  
  1196.     TRY
  1197.     {
  1198.         ODBoolean hasIcon = kODFalse;
  1199.         for(int i = 1; i <= 6; i++)
  1200.         {
  1201.             OSErr err = noErr;
  1202.             DTPBRec pb;
  1203.             memset(&pb,'\0',sizeof(DTPBRec));
  1204.             
  1205.             pb.ioCompletion = NULL;
  1206.             pb.ioDTRefNum     = DTRefNum;
  1207.             pb.ioTagInfo     = 0; // Reserved ; must be zero
  1208.             pb.ioDTBuffer     = (Ptr)&iconBuffer;
  1209.             pb.ioDTReqCount = sizeof(iconBuffer);
  1210.             pb.ioIconType     = i; // index
  1211.             pb.ioFileCreator= fileCreator;
  1212.             pb.ioFileType     = fileType;
  1213.             err = ::PBDTGetIconSync(&pb);
  1214.             
  1215.             if (err == noErr)
  1216.             {
  1217.                 WASSERT(pb.ioDTActCount == kIconSize[i-1]);
  1218.                 Handle hIcon =  ODNewHandle(kIconSize[i-1]);
  1219.                 HLock(hIcon);
  1220.                 ODBlockMove(iconBuffer,*hIcon,kIconSize[i-1]);
  1221.                 HUnlock(hIcon);
  1222.                 err = AddIconToSuite(hIcon ,icons, kIconType[i-1] );
  1223.                 if(err)
  1224.                 {
  1225.                     DisposeHandle(hIcon);
  1226.                     hIcon = kODNULL;
  1227.                     THROW_IF_ERROR(err);
  1228.                 }
  1229.                 hasIcon = kODTrue;
  1230.             }
  1231.             else if (err != afpItemNotFound)
  1232.             {
  1233.                 THROW_IF_ERROR(err);
  1234.             }
  1235.         } // For loop
  1236.             
  1237.         // return NULL if we could not find any icon data. 
  1238.         if (!hasIcon)
  1239.         {
  1240.             if (icons)
  1241.                 DisposeIconSuite(icons, kDisposeHandlesInIconSuite);
  1242.             icons = kODNULL;
  1243.         }
  1244.     } // TRY
  1245.     CATCH_ALL
  1246.         if (icons)
  1247.             DisposeIconSuite(icons, kDisposeHandlesInIconSuite);
  1248.         icons = kODNULL;
  1249.         RERAISE;
  1250.     ENDTRY
  1251.     
  1252.     return icons;
  1253. }
  1254.  
  1255.  
  1256. //--------------------------------------------------------------------
  1257. // ODSetIconFamily
  1258. //--------------------------------------------------------------------
  1259.  
  1260. void    ODSetIconFamily(Environment* ev, 
  1261.                 ODFrame* frame, ODIconFamily icons, ODBoolean deleteOtherPlatformIcons)
  1262. {
  1263.     TempODPart         part = frame->AcquirePart(ev);
  1264.     
  1265.     ODSetPOIconFamily(ev, part, icons, deleteOtherPlatformIcons);
  1266.     
  1267.     TempPlatformFile usersFile = ODGetFileIfRoot(ev, frame);
  1268.     if (usersFile) {
  1269.         usersFile->SetCustomIconFamily(icons);
  1270.     }
  1271. }
  1272.  
  1273. //--------------------------------------------------------------------
  1274. // ODGetFileIfRoot
  1275. //--------------------------------------------------------------------
  1276.  
  1277. PlatformFile*    ODGetFileIfRoot(Environment* ev, ODFrame* frame)
  1278. {
  1279.     ASSERT_NOT_NULL(frame);
  1280.  
  1281.     PlatformFile* file = kODNULL;
  1282.     
  1283.     TempODPart part = frame->AcquirePart(ev);
  1284.  
  1285.     // Get the root part of the document.
  1286.     ODDraft* draft = ODGetDraft(ev,part);
  1287.     TempODPart rootPart = ODAcquireRootPartOfDraft(ev, draft);
  1288.     
  1289.     // If the part is the root of the document, return the corresponding file.
  1290.     if ( ODObjectsAreEqual(ev, part, rootPart) )
  1291.     {
  1292.         ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);
  1293.         file = GetPlatformFileFromContainer(ev, container);
  1294.     }
  1295.     
  1296.     return file;
  1297. }
  1298.  
  1299. //--------------------------------------------------------------------
  1300. // DetachIconProc
  1301. //--------------------------------------------------------------------
  1302.  
  1303. static OSErr DetachIconProc( ResType, Handle *theIcon, void */*yourDataPtr*/ )
  1304. {
  1305.     if( *theIcon ) {
  1306.         DetachResource(*theIcon);
  1307.         return ResError();
  1308.     } else
  1309.         return noErr;
  1310. }
  1311.  
  1312. //--------------------------------------------------------------------
  1313. // GetGenericIcon
  1314. //--------------------------------------------------------------------
  1315.  
  1316. ODStatic ODIconFamily GetGenericIcon( short iconID )
  1317. {
  1318.     ODIconFamily icon;
  1319.     THROW_IF_ERROR( GetIconSuite( &icon, iconID, svAllAvailableData ) );
  1320.     IconActionUPP detachProc = NewIconActionProc(&DetachIconProc);
  1321.     (void) ForEachIconDo(icon, svAllAvailableData, detachProc, kODNULL);
  1322.     DisposeRoutineDescriptor(detachProc);
  1323.     return icon;
  1324. }
  1325.  
  1326.  
  1327. //--------------------------------------------------------------------
  1328. // ODGetIsStationery
  1329. //--------------------------------------------------------------------
  1330.  
  1331. ODBoolean    ODGetIsStationery(Environment* ev, 
  1332.                 ODFrame* frame)
  1333. {
  1334.     TempODPart        part = frame->AcquirePart(ev);
  1335.     ODBoolean        isStationery = kODFalse;
  1336.     
  1337.     TempPlatformFile usersFile = ODGetFileIfRoot(ev, frame);
  1338.     if (usersFile)
  1339.         isStationery = usersFile->IsStationery();
  1340. //    else
  1341. //        isStationery = ODGetSUIsStationery(ev, ODGetSUFromPstObj(ev, part));
  1342.     return isStationery;
  1343. }
  1344.  
  1345. //--------------------------------------------------------------------
  1346. // ODSetIsStationery
  1347. //--------------------------------------------------------------------
  1348.  
  1349. void        ODSetIsStationery(Environment* ev, 
  1350.                 ODFrame* frame, ODBoolean isStationery)
  1351. {
  1352. //    { TempODPart part = frame->AcquirePart(ev);
  1353. //      ODSetBooleanProp( ev, ODGetSUFromPstObj(ev, part),
  1354. //                            kODPropIsStationery, kODBoolean, isStationery);
  1355. //    }
  1356.     TempPlatformFile usersFile = ODGetFileIfRoot(ev, frame);
  1357.     if (usersFile)
  1358.         usersFile->SetStationery(isStationery);
  1359. }
  1360. #if 0
  1361. //--------------------------------------------------------------------
  1362. // ODSetSUIsStationery
  1363. //--------------------------------------------------------------------
  1364.  
  1365. void        ODSetSUIsStationery(Environment* ev, 
  1366.                 ODStorageUnit* su, ODBoolean isStationery)
  1367. {
  1368.     ODSetBooleanProp( ev, su, kODPropIsStationery, kODBoolean, isStationery);
  1369. }
  1370.  
  1371. //--------------------------------------------------------------------
  1372. // ODGetSUIsStationery
  1373. //--------------------------------------------------------------------
  1374.  
  1375. ODBoolean        ODGetSUIsStationery(Environment* ev, 
  1376.                 ODStorageUnit* su)
  1377. {
  1378.     ODBoolean isStationery;
  1379.     
  1380.     if (su->Exists(ev, kODPropIsStationery, kODBoolean, 0))
  1381.         isStationery = ODGetBooleanProp( ev, su, kODPropIsStationery, kODBoolean);
  1382.     else
  1383.         isStationery = kODFalse;
  1384.         
  1385.     return isStationery;
  1386. }
  1387. #endif /* 0 */
  1388. //-------------------------------------------------------------------------------------
  1389. // Editor and Kind Menu manipulation functions
  1390. //-------------------------------------------------------------------------------------
  1391. // copied from LinkDlgs.cpp (with changes by TÇ)
  1392. //------------------------------------------------------------------------------
  1393. // InitKindsPopup
  1394. //------------------------------------------------------------------------------
  1395.  
  1396. void InitKindsPopup (     ODTypeList* kindList,
  1397.                         ODType theKind,
  1398.                         ControlHandle    itemHandle,
  1399.                         ODSShort valueCount,
  1400.                         ODSShort* currentKindItem,
  1401.                         MenuHandle kindMenu,
  1402.                         ODSShort* translateItem,
  1403.                         ODSession* session,
  1404.                         ODStorageUnit* thePartSU)
  1405. {
  1406.     ODSShort        item = 1;
  1407.  
  1408.     Environment* ev = somGetGlobalEnvironment();
  1409.  
  1410.     ODUShort i;
  1411.  
  1412.     // remove all except last item in menu
  1413.     for (i = CountMItems(kindMenu) - 1;  i > 0;  --i) 
  1414.     {
  1415.         DeleteMenuItem(kindMenu, i);
  1416.     }
  1417.  
  1418.     AddTypesToMenu(kindList, kindMenu, theKind, valueCount, currentKindItem, session, thePartSU);
  1419.  
  1420.     *translateItem = CountMItems(kindMenu);
  1421.     EnableItem(kindMenu, *translateItem);
  1422.  
  1423.     SetControlMinimum(itemHandle, 1);
  1424.     SetControlMaximum(itemHandle, *translateItem);
  1425.     SetControlValue(itemHandle, *currentKindItem);
  1426.  
  1427.     // Determine if translation is an option
  1428.     ODTypeList*    translateToList =
  1429.         session->GetStorageSystem(ev)->CreateTypeList(ev,(ODTypeList*)kODNULL);
  1430.     
  1431.     TRY
  1432.         GetDestinationKindsList(kindList, translateToList, kODNULL, session);
  1433.         if ( translateToList->Count(ev) == 0 )
  1434.             DisableItem(kindMenu, *translateItem);
  1435.     CATCH_ALL
  1436.         DisableItem(kindMenu, *translateItem);
  1437.     ENDTRY
  1438.     
  1439.     ODDeleteObject( translateToList );
  1440. }
  1441.  
  1442. //------------------------------------------------------------------------------
  1443. // InsertMenuItemIgnoreMeta
  1444. //------------------------------------------------------------------------------
  1445. ODStatic ODSShort InsertMenuItemIgnoreMeta(MenuHandle menu, ConstStr255Param itemString, ODSShort item)
  1446. {
  1447.     InsertMenuItem(menu, "\p ", item++);
  1448.     SetMenuItemText(menu, item, itemString);
  1449.     return item;
  1450. }
  1451.  
  1452. #ifdef _OD_IMPL_
  1453. //------------------------------------------------------------------------------
  1454. // AddTypesToMenu
  1455. //------------------------------------------------------------------------------
  1456.  
  1457. void AddTypesToMenu(ODTypeList* typeList, MenuHandle kindMenu, ODType defaultKind, 
  1458.                     ODSShort valueCount, ODSShort* currentKindItem, ODSession* session,
  1459.                     ODStorageUnit* thePartSU)
  1460. {
  1461.     ODName*                name = kODNULL; ODVolatile(name);
  1462.     ODSShort            item = 0;
  1463.     Environment*        ev = somGetGlobalEnvironment();
  1464.     ODNameSpaceManager*    nsm = session->GetNameSpaceManager(ev);
  1465.     ODULong                prefixSize = ODISOStrLength(kODAppleFileTypePrefix);
  1466.     
  1467.     ODTypeListIterator* typeIter = typeList->CreateTypeListIterator(ev);
  1468.     
  1469.     EditorSet*            editorList = new EditorSet;
  1470.     editorList->InitEditorSet();
  1471.  
  1472.     for (ODType type = typeIter->First(ev);
  1473.         typeIter->IsNotComplete(ev);
  1474.         type = typeIter->Next(ev))
  1475.     {
  1476.     ODBoolean isDefaultKind =  defaultKind ? ODISOStrEqual(type, defaultKind) : kODFalse;
  1477.     ODBoolean usingPersistentName = kODFalse;
  1478.     
  1479.     ODBoolean userStringFound = GetUserKindFromKind(nsm, type, &name);
  1480.     
  1481.     if (isDefaultKind && !userStringFound && thePartSU)
  1482.     {
  1483.         TRY
  1484.  
  1485.         name = ODGetITextProp(ev, thePartSU,
  1486.                             kODPropPreferredKindUserString, kODMacIText, kODNULL);        
  1487.         CATCH_ALL
  1488.             // if we fail, ignore ;  its just cosemetic
  1489.             WARN("Error getting kODPropPreferredKindUserString");
  1490.         ENDTRY
  1491.                                 
  1492.         if( name )
  1493.             usingPersistentName = kODTrue;
  1494.         else
  1495.             usingPersistentName = kODFalse;
  1496.     }
  1497.     
  1498.     if ( usingPersistentName || userStringFound )
  1499.     {
  1500.         Str255 itemString;
  1501.         IntlToPStr(name, itemString);
  1502.         item = InsertMenuItemIgnoreMeta(kindMenu, itemString, item);
  1503.         
  1504.         ScriptCode itemScript = GetITextScriptCode(name);
  1505.         SetPopupItemScript(kindMenu, item, itemScript);
  1506.         
  1507.         DisposeIText( name );
  1508.     }
  1509.     else
  1510.     {
  1511.         // there's no name for this type
  1512.         Str255 pKindStr;
  1513.         ODTranslation* translation = session->GetTranslation(ev);
  1514.         ODPlatformType platformType = 
  1515.             translation->GetPlatformTypeFromISOType(ev, type);
  1516.         if ( platformType == kODNULL )
  1517.         {
  1518.             // Special menu item
  1519.             CUsingLibraryResources r;
  1520.             GetIndString(pKindStr, kODInfoUtilStrsID, kODStrIndNoKinds); 
  1521.         }
  1522.         else
  1523.         {
  1524.             ODBlockMove(&platformType, &(pKindStr[1]), (ODULong) sizeof(ODPlatformType));
  1525.             pKindStr[0] = (unsigned char) sizeof(ODPlatformType);
  1526.         }
  1527.         // Allow metacharacters in item text
  1528.         item = InsertMenuItemIgnoreMeta(kindMenu, pKindStr, item);
  1529.     }
  1530.  
  1531.     // if it is a file type that is not the default type, we would disable it
  1532.     // we also disable it if if cannot find any editor for the kind
  1533.     if (item > valueCount)
  1534.         if ((ODISOStrNCompare(kODAppleFileTypePrefix, (ODISOStr) type, prefixSize) == 0) ||
  1535.                 (!GetAllEditorsForKind(nsm, type, editorList)))
  1536.             DisableItem(kindMenu, item);
  1537.     editorList->RemoveAllEditors();
  1538.     
  1539.     if (isDefaultKind)
  1540.         *currentKindItem = item;
  1541.     
  1542.     ODDisposePtr(type);
  1543.     }
  1544.     ODDeleteObject( editorList );
  1545.     ODDeleteObject( typeIter );
  1546. }
  1547.  
  1548. //------------------------------------------------------------------------------
  1549. // EnableTypesInMenu
  1550. //------------------------------------------------------------------------------
  1551.  
  1552. ODUShort EnableTypesInMenu(
  1553.                     ODTypeList*            typeList,
  1554.                     MenuHandle            kindMenu,
  1555.                     ODEditor            editor,
  1556.                     ODNameSpaceManager*    nsm)
  1557. {
  1558.     Environment* ev = somGetGlobalEnvironment();
  1559.     ODUShort itemStart = 0;
  1560.  
  1561.     if ( kindMenu && typeList && (typeList->Count(ev) > 0) )
  1562.     {
  1563.         ODTypeListIterator* typeIter = typeList->CreateTypeListIterator(ev);
  1564.         
  1565.         for (ODType type = typeIter->First(ev);
  1566.             typeIter->IsNotComplete(ev);
  1567.             type = typeIter->Next(ev))
  1568.         {
  1569.             if ( editor == kODNULL )
  1570.             {
  1571.                 // Editor is not fixed; Aassume kind can be embedded even if there is
  1572.                 // no editor installed for it
  1573.                 EnableItem(kindMenu, ++itemStart);
  1574.             }
  1575.             else
  1576.             {
  1577.                 if ( EditorSupportsKind(nsm, editor, type) )
  1578.                     EnableItem(kindMenu, ++itemStart);
  1579.                 else
  1580.                     DisableItem(kindMenu, ++itemStart);
  1581.             }
  1582.             ODDisposePtr(type);
  1583.         }
  1584.     
  1585.         ODDeleteObject( typeIter );
  1586.     }
  1587.     
  1588.     return itemStart;
  1589. }
  1590. #endif
  1591.  
  1592. //------------------------------------------------------------------------------
  1593. // DeleteAllMenuItems
  1594. //------------------------------------------------------------------------------
  1595. ODStatic void DeleteAllMenuItems(MenuHandle theMenu)
  1596. {
  1597.     ODUShort i;
  1598.  
  1599.     for (i = CountMItems(theMenu);  i > 0;  --i)
  1600.     {
  1601.         DeleteMenuItem(theMenu, i);
  1602.     }
  1603. }
  1604.  
  1605. #ifdef _OD_IMPL_
  1606. //------------------------------------------------------------------------------
  1607. // SetupEditorMenu
  1608. //------------------------------------------------------------------------------
  1609. ODBoolean SetupEditorMenu(ODType kind,
  1610.                             EditorSet* editorList,
  1611.                             MenuHandle editorMenu, 
  1612.                             ControlHandle popupCtlHndl, 
  1613.                             ODSession* session,
  1614.                             ODStorageUnit* thePartSU)
  1615. {    
  1616.     ODBoolean anyEditors = (editorList->GetEditorCount() > 0);
  1617.     
  1618.     Environment* ev = somGetGlobalEnvironment();
  1619.     ODNameSpaceManager* nsm = session->GetNameSpaceManager(ev);
  1620.  
  1621.     // And remove all items from the editors menu
  1622.     DeleteAllMenuItems(editorMenu);
  1623.  
  1624.         // Get all editors supporting that kind; Preferred editor must be first
  1625.         if ( kind && !anyEditors)
  1626.         {
  1627.             ODEditor prefEditor = GetSysPrefEditorForKind(nsm, kind);
  1628.             if ( prefEditor )
  1629.                 editorList->AddEditor(prefEditor);
  1630.             ODDisposePtr((ODPtr) prefEditor);
  1631.             anyEditors = GetAllEditorsForKind(nsm, kind, editorList);
  1632.         }
  1633.  
  1634.         if ( anyEditors )
  1635.         {
  1636.             AddEditorsToMenu(editorList, editorMenu, session,thePartSU);
  1637.             if ( popupCtlHndl )
  1638.             {
  1639.                 SetControlMaximum(popupCtlHndl, editorList->GetEditorCount());
  1640.                 HiliteControl(popupCtlHndl, kControlActive);
  1641.             }
  1642.         }
  1643.         else
  1644.         {
  1645.             // The editor popup should be inactive, remove all editors
  1646.             editorList->RemoveAllEditors();
  1647.         }
  1648.     
  1649.     if ( popupCtlHndl )
  1650.     {
  1651.         SetControlMinimum(popupCtlHndl, 1);
  1652.         SetControlValue(popupCtlHndl, 1);
  1653.     }
  1654.     
  1655.     return anyEditors;
  1656. }
  1657. #endif
  1658.  
  1659. //------------------------------------------------------------------------------
  1660. // AddEditorsToMenu
  1661. //------------------------------------------------------------------------------
  1662.  
  1663. void AddEditorsToMenu(EditorSet* editorList,
  1664.                                 MenuHandle editorMenu, 
  1665.                                 ODSession* session,
  1666.                                 ODStorageUnit* thePartSU)
  1667. {
  1668.     ODName*        name;
  1669.     Str255         pEditorString;
  1670.     ODSShort        item = 0;
  1671.     Environment*         ev = somGetGlobalEnvironment();
  1672.     ODNameSpaceManager*    nsm = session->GetNameSpaceManager(ev);
  1673.     
  1674.     EditorSetIterator* editorIter = editorList->CreateIterator();
  1675.     
  1676.     ODType nextEditor = kODNULL;
  1677.     for (ODType editor = editorIter->First();
  1678.         editorIter->IsNotComplete();
  1679.         editor = nextEditor)
  1680.     {
  1681.         nextEditor = editorIter->Next();
  1682.         if (GetUserEditorFromEditor(nsm, editor, &name))
  1683.         {
  1684.             TempODName tempName = name; // DMc: ensure it's deleted
  1685.             IntlToPStr(name, pEditorString);
  1686.  
  1687.             // Can't call IsNoPart because BindingUtil.h is an internal interface
  1688.             // not for use by part developers. Even though this routine is internal
  1689.             // to OpenDoc, it resides in a public utility file.
  1690.             // $$$$$ Internal utilities should be removed from public utilities sources.
  1691.             // - RA
  1692.             if (ODISOStrEqual(editor,kODBlackBoxHandlerOfLastResort))
  1693.             {
  1694.                 LOG("Showing Apple default for NoPart");
  1695.                 
  1696.                 TempODName editorName = kODNULL; //ODVolatile(editorName); won't be set if error occurs
  1697.                 
  1698.                 TRY
  1699.                         
  1700.                 ODULong size;
  1701.                 TempODEditor preferredEditor = ODGetISOStrProp(ev, thePartSU, 
  1702.                             kODPropPreferredEditor, kODEditor, kODNULL, &size);
  1703.                 if ((editorList->ContainsEditor(preferredEditor)))
  1704.                 {
  1705.                     editorList->RemoveEditor(preferredEditor);
  1706.                     break; // OK to break in TRY for C++
  1707.                 }
  1708.                 else
  1709.                 {
  1710.                     editorName = ODGetITextProp(ev, thePartSU,
  1711.                                         kODPropPreferredEditorUserString, kODMacIText, kODNULL);
  1712.                 }
  1713.                 CATCH_ALL
  1714.                     WARN("Error getting the kODPropPreferredEditor prop");
  1715.                 ENDTRY
  1716.                 
  1717.                 if (editorName)
  1718.                 {
  1719.                     GetITextPString(editorName,pEditorString); 
  1720.                     item = InsertMenuItemIgnoreMeta(editorMenu, pEditorString, item);
  1721.                 }
  1722.                 else
  1723.                 {    //business as usual
  1724.                 
  1725.                     LOG("Could not get user string from SU");
  1726.                     item = InsertMenuItemIgnoreMeta(editorMenu, pEditorString, item);
  1727.                 }
  1728.             }
  1729.             else
  1730.                 item = InsertMenuItemIgnoreMeta(editorMenu, pEditorString, item);
  1731.                 
  1732.             EnableItem(editorMenu, item);
  1733.             // comments for SetPopupItemScript say don't call unless the script
  1734.             // needs setting, but there's no way to test that here.  Sounds like
  1735.             // an optimization to me....
  1736.             SetPopupItemScript( editorMenu, item, GetITextScriptCode(name) );
  1737.         }
  1738.         else
  1739.         {
  1740.              // Special menu item in italics
  1741.             CUsingLibraryResources r;
  1742.             GetIndString(pEditorString, kODInfoUtilStrsID, kODStrIndNoEditors); 
  1743.  
  1744.             item = InsertMenuItemIgnoreMeta(editorMenu, pEditorString, item);
  1745.             DisableItem(editorMenu, item);
  1746.         }
  1747.     }
  1748.  
  1749.     ODDeleteObject( editorIter );
  1750. }
  1751.  
  1752. //------------------------------------------------------------------------------
  1753. // GetThisEditorFromList
  1754. //------------------------------------------------------------------------------
  1755. ODEditor GetThisEditorFromList(ODSShort editorIndex, EditorSet* editorList)
  1756. {
  1757.     ODEditor result = kODNULL;
  1758.     
  1759.     if ( editorIndex > 0 )
  1760.     {
  1761.         ODEditor editor;
  1762.         EditorSetIterator* iter = editorList->CreateIterator();
  1763.         
  1764.         for ( editor = iter->First(); 
  1765.               (--editorIndex > 0) && iter->IsNotComplete(); 
  1766.               editor = iter->Next() )
  1767.         {
  1768.         }
  1769.     
  1770.         delete iter;
  1771.         
  1772.         if ( editor != kODNULL )
  1773.             result = ODISOStrFromCStr((char *) editor);
  1774.     }
  1775.  
  1776.     return result;
  1777. }
  1778.  
  1779. //------------------------------------------------------------------------------
  1780. // IndexOfEditorInList
  1781. //------------------------------------------------------------------------------
  1782. ODSShort IndexOfEditorInList(EditorSet* editorList, ODEditor editor)
  1783. {
  1784.     ODSShort retVal = 0;
  1785.     
  1786.     if ( editorList->GetEditorCount() )
  1787.     {
  1788.         ODSShort i = 1;
  1789.         EditorSetIterator* editorIter = editorList->CreateIterator();
  1790.         
  1791.         for (ODEditor anEditor = editorIter->First();
  1792.             editorIter->IsNotComplete();
  1793.             anEditor = editorIter->Next())
  1794.         {
  1795.             if ( (anEditor == editor) || ODISOStrEqual(anEditor, editor) )
  1796.             {
  1797.                 retVal = i;
  1798.                 break;
  1799.             }
  1800.             i++;
  1801.         }
  1802.  
  1803.         ODDeleteObject( editorIter );
  1804.     }
  1805.     
  1806.     return retVal;
  1807. }
  1808.  
  1809. //------------------------------------------------------------------------------
  1810. // IndexOfKindInList
  1811. //------------------------------------------------------------------------------
  1812. ODSShort IndexOfKindInList(ODTypeList* kindList, ODType kind)
  1813. {
  1814.     ODSShort retVal = 0;
  1815.     
  1816.     Environment* ev = somGetGlobalEnvironment();
  1817.  
  1818.     if ( kindList->Count(ev) )
  1819.     {
  1820.         ODSShort i = 1;
  1821.         ODTypeListIterator* kindIter = kindList->CreateTypeListIterator(ev);
  1822.         
  1823.         TRY
  1824.         
  1825.             for (ODType type = kindIter->First(ev);
  1826.                 kindIter->IsNotComplete(ev);
  1827.                 type = kindIter->Next(ev), i++)
  1828.             {
  1829.                 if ( ODISOStrEqual(type, kind) )
  1830.                     retVal = i;
  1831.                 ODDisposePtr(type);
  1832.                 if ( retVal != 0 )
  1833.                     break;
  1834.             }
  1835.  
  1836.         CATCH_ALL
  1837.             ODDeleteObject(kindIter);
  1838.             RERAISE;
  1839.         ENDTRY
  1840.         
  1841.         ODDeleteObject(kindIter);
  1842.     }
  1843.     
  1844.     return retVal;
  1845. }
  1846.  
  1847. //------------------------------------------------------------------------------
  1848. // GetThisKindFromList
  1849. //------------------------------------------------------------------------------
  1850. ODType GetThisKindFromList(ODSShort kindItem, ODTypeList* kindList)
  1851. {
  1852.     Environment* ev = somGetGlobalEnvironment();
  1853.     ODType type = kODNULL;
  1854.     ODTypeListIterator* kindIter = kindList->CreateTypeListIterator(ev);
  1855.  
  1856.     for ( type = kindIter->First(ev); 
  1857.           (--kindItem > 0) && kindIter->IsNotComplete(ev); 
  1858.           type = kindIter->Next(ev) )
  1859.     {
  1860.         ODDisposePtr(type);
  1861.         type = kODNULL;
  1862.     }
  1863.  
  1864.     ODDeleteObject(kindIter);
  1865.  
  1866.     return type;
  1867. }
  1868.  
  1869.  
  1870. //------------------------------------------------------------------------------
  1871. // ContentValueTypes
  1872. //------------------------------------------------------------------------------
  1873. void ContentValueTypes(ODStorageUnit* contentSU, ODTypeList* typeList)
  1874. {
  1875.     TempODType hfsType = kODNULL;
  1876.  
  1877.     TRY
  1878.         ODULong        count;
  1879.         ODULong        index;
  1880.         
  1881.         Environment* ev = somGetGlobalEnvironment();
  1882.  
  1883.         ODTranslation* translation = contentSU->GetSession(ev)->GetTranslation(ev);
  1884.         hfsType = translation->GetISOTypeFromPlatformType(ev, kODFileType_hfs, kODPlatformDataType);
  1885.  
  1886.         contentSU->Focus(ev, kODPropContents, kODPosUndefined, 0, 0, kODPosUndefined);
  1887.         count = contentSU->CountValues(ev);
  1888.         for (index = 1; index <= count; ++index)
  1889.         {
  1890.             contentSU->Focus(ev, kODPropContents, kODPosUndefined, 0, index, kODPosUndefined);
  1891.             TempODType type = contentSU->GetType(ev);
  1892.             if ( !ODISOStrEqual(type, hfsType) )
  1893.                 typeList->AddLast(ev, type);
  1894.         }
  1895.     CATCH_ALL
  1896.     ENDTRY
  1897. }
  1898.  
  1899. //------------------------------------------------------------------------------
  1900. // ODUserRenameFile
  1901. //------------------------------------------------------------------------------
  1902.  
  1903.  
  1904. ODStatic ODBoolean ODUserRenameFile(Environment* ev,
  1905.                     ODSession* session, 
  1906.                     PlatformFile*    usersFile, 
  1907.                     ODIText* name,
  1908.                     DescType replaceOption)
  1909. {
  1910.     ODBoolean    fileRenamed = kODFalse;
  1911.     
  1912.     // name to aStr255
  1913.     Str255 aStr255;
  1914.     
  1915.     GetITextPString(name, aStr255);
  1916.  
  1917.     TRY
  1918.         usersFile->Rename(aStr255);
  1919.         fileRenamed = kODTrue;
  1920.     CATCH_ALL
  1921.         if (ErrorCode() == dupFNErr)
  1922.         {
  1923.             switch (replaceOption) {
  1924.             case kAEAsk:
  1925.                 ParamText(aStr255, "\p","\p","\p");
  1926.                 fileRenamed = ODAskUserReplace(ev, session);
  1927.                 if (!fileRenamed)
  1928.                     THROW(userCanceledErr);
  1929.                 break;
  1930.             case kAEYes:
  1931.                 fileRenamed = kODTrue; break;
  1932.             case kAENo:
  1933.                 fileRenamed = kODFalse; break;
  1934.             }
  1935.             
  1936.             if (fileRenamed)
  1937.             {
  1938.                 ODFileSpec fsspec = usersFile->GetFileSpec();
  1939.                 ODError result = HDelete(fsspec.vRefNum,fsspec.parID,aStr255);
  1940.                 if ( result!=wPrErr && result!=fLckdErr && 
  1941.                                     result!=fBsyErr && result!=afpAccessDenied )
  1942.                 {
  1943.                     TRY
  1944.                         usersFile->Rename(aStr255);
  1945.                     CATCH_ALL
  1946.                         WARN("File renaming failed, err %ld",ErrorCode());
  1947.                         fileRenamed = kODFalse;
  1948.                     ENDTRY
  1949.                 }
  1950.                 else
  1951.                 {
  1952.                     fileRenamed = kODFalse;
  1953.                     if (replaceOption == kAEAsk)
  1954.                         switch(result)
  1955.                         {
  1956.                             case wPrErr:
  1957.                             case fLckdErr:
  1958.                             case fBsyErr:
  1959.                             {
  1960.                                 CUsingLibraryResources res;
  1961.                                 StopAlert(kFilelockedAlrtID, GetODDialogFilter());
  1962.                                 break;
  1963.                             }
  1964.                             default:
  1965.                                 SysBeep(2);
  1966.                         }
  1967.                     else
  1968.                         SysBeep(2);
  1969.                 }
  1970.             }
  1971.         }
  1972.         else 
  1973.             RERAISE;
  1974.     ENDTRY
  1975.     return( fileRenamed );
  1976. }
  1977.  
  1978. //------------------------------------------------------------------------------
  1979. // ODAskUserReplace
  1980. //------------------------------------------------------------------------------
  1981.  
  1982. ODBoolean    ODAskUserReplace(Environment* ev,
  1983.                             ODSession* session)
  1984. // Pass in the name in question via ParamText(^0).
  1985. {  
  1986.     CUsingLibraryResources r;
  1987.     ODBoolean    doReplace    = kODFalse;
  1988.     short          itemHit     = 0;
  1989.     DialogPtr     dlg         = ODGetNewDialog(ev, kNameConflictDlgID, 
  1990.                                     session, kODFalse );
  1991.     if (dlg)
  1992.     {
  1993.         Handle        scratchHandle = kODNULL;
  1994.         Rect        scratchRect;
  1995.  
  1996.         SetPort(dlg);
  1997.         
  1998.             // Set the draw routine for the default button outline item
  1999.         GetDialogItem(dlg, kNameConflictDefaultButtonItem, &itemHit, &scratchHandle, &scratchRect);
  2000.         SetDialogItem(dlg, kNameConflictDefaultButtonItem, itemHit, 
  2001.                  (Handle)GetODOutlineDefaultButtonDrawProc(), &scratchRect);
  2002.                 
  2003.         ShowWindow(dlg);
  2004.  
  2005.         do {
  2006.             ModalDialog(GetODDialogFilter(), &itemHit);
  2007.             switch(itemHit)
  2008.             {
  2009.                 case kNameConflictReplaceBtn:
  2010.                     doReplace = kODTrue;
  2011.                     break;
  2012.                 case kNameConflictCancelBtn:
  2013.                     break;
  2014.             }
  2015.         } while ((itemHit != kNameConflictReplaceBtn) && 
  2016.                                         (itemHit != kNameConflictCancelBtn));
  2017.                 
  2018.         ODDisposeDialog(dlg);
  2019.     }
  2020.     return doReplace;
  2021. }
  2022.  
  2023. //------------------------------------------------------------------------------
  2024. //    CommentsDontMatch
  2025. //
  2026. //    This compares 2 ODIText strings to see if they match and returns TRUE if
  2027. //    they do not match.  It take into account the fact that the comments field
  2028. //    of the desktop database clips its string to 200 characters.
  2029. //
  2030. //    Returns false if the strings are identical but the script/language are
  2031. //    not.  This is because these values in dtComments have been set using
  2032. //    system defaults while those in propComments were actually saved, and
  2033. //    should therefore take precedence. <eeh>
  2034. //
  2035. //    propComments can be NULL, dtComments cannot
  2036. //------------------------------------------------------------------------------
  2037.  
  2038. ODBoolean
  2039. CommentsDontMatch(ODIText* dtComments, ODIText* propComments)
  2040. {
  2041.     ODBoolean    result;
  2042.     ODULong        dtLen, propLen;
  2043.     Str255        dtStr, propStr;
  2044.     
  2045.     if (dtComments != kODNULL)
  2046.         dtLen = GetITextStringLength(dtComments);
  2047.     else
  2048.         dtLen = 0;
  2049.     if (propComments == kODNULL)
  2050.         return (dtLen != 0);
  2051.     propLen = GetITextStringLength(propComments);
  2052.     if (dtLen == 0)
  2053.         return (propLen != 0);
  2054.     
  2055.     // if either string is length 0 (or NULL) we won't get here
  2056.     WASSERT(dtComments && propComments);
  2057.     result = kODTrue;
  2058.  
  2059.     // because the Finder does not store script and language with the
  2060.     // comments or file names, we ignore these in comparing strings.  That
  2061.     // is, if the strings are identical byte-for-byte, we consider them
  2062.     // to be equal.  That way, the string *we* stored will be used, as will
  2063.     // the script and language information we stored with it.
  2064.  
  2065.     ODBoolean lengthsMatch =
  2066.             (dtLen == propLen) || (dtLen == 200 && propLen >= 200);
  2067.     if ( lengthsMatch )
  2068.     {
  2069.         GetITextPString(dtComments, (StringPtr) &dtStr);
  2070.         GetITextPString(propComments, (StringPtr) &propStr);
  2071.         propStr[0] = dtStr[0];            // fix the 200 case
  2072.         result = !EqualString( dtStr, propStr, kODTrue, kODTrue );
  2073.     }
  2074.     return result;
  2075.  
  2076. }
  2077.  
  2078.  
  2079. void SetAllWindowShowLinks(Environment* ev, ODWindowState* winState, ODBoolean showLinks)
  2080. {
  2081.     ODWindowIterator* iter = kODNULL; ODVolatile(iter);
  2082.             
  2083.     TRY
  2084.  
  2085.         iter = winState->CreateWindowIterator(ev);
  2086.     
  2087.         for (ODWindow* window = iter->First(ev); iter->IsNotComplete(ev);
  2088.                 window = iter->Next(ev))
  2089.         {
  2090.             if (window)
  2091.             {
  2092.                 window->SetShouldShowLinks(ev, showLinks);
  2093.                 ODFrame* root = window->GetRootFrame(ev);
  2094.                 root->Invalidate(ev, kODNULL, kODNULL);
  2095.             }
  2096.         }
  2097.         ODDeleteObject(iter);
  2098.  
  2099.     
  2100.     CATCH_ALL
  2101.  
  2102.         ODDeleteObject(iter);
  2103.         RERAISE;
  2104.  
  2105.     ENDTRY
  2106. }
  2107.  
  2108. //------------------------------------------------------------------------------
  2109. // TranslateValueTypes
  2110. //------------------------------------------------------------------------------
  2111. void TranslateValueTypes(
  2112.                 ODTypeList*    kindList,
  2113.                 ODTypeList*    translateToList,
  2114.                 OrderedCollection* translateFromList,
  2115.                 ODSession*    session)
  2116. {
  2117.     Environment* ev = somGetGlobalEnvironment();
  2118.  
  2119.     ODTranslation* translation = session->GetTranslation(ev);
  2120.  
  2121.     ODTypeListIterator* kindIter = kindList->CreateTypeListIterator(ev);
  2122.     
  2123.     ODUShort kindIndex = 0;
  2124.  
  2125.     for (ODType kind = kindIter->First(ev);
  2126.         kindIter->IsNotComplete(ev);
  2127.         kind = kindIter->Next(ev))
  2128.     {
  2129.         ++kindIndex;
  2130.  
  2131.         TRY
  2132.             ODTypeList* toList = translation->GetTranslationOf(ev, kind);
  2133.             
  2134.             ODTypeListIterator* toIter = toList->CreateTypeListIterator(ev);
  2135.             
  2136.             for (ODType toKind = toIter->First(ev);
  2137.                 toIter->IsNotComplete(ev);
  2138.                 toKind = toIter->Next(ev))
  2139.             {
  2140.                 TRY
  2141.                 
  2142.                     if ( (kindList->Contains(ev, toKind) == kODFalse)
  2143.                         &&
  2144.                          (translateToList->Contains(ev, toKind) == kODFalse)
  2145.                        )
  2146.                     {
  2147.                         translateToList->AddLast(ev, toKind);
  2148.                         translateFromList->AddLast((void*) kindIndex);
  2149.                     }
  2150.                 
  2151.                 CATCH_ALL
  2152.                 ENDTRY
  2153.                 ODDisposePtr(toKind);
  2154.             }
  2155.             delete toIter;
  2156.             delete toList;
  2157.  
  2158.         CATCH_ALL
  2159.         ENDTRY
  2160.  
  2161.         ODDisposePtr(kind);
  2162.     }
  2163.     delete kindIter;
  2164. }
  2165.  
  2166. //------------------------------------------------------------------------------
  2167. // StringPtrFromStrHandle
  2168. //------------------------------------------------------------------------------
  2169.  
  2170. ODStatic StringPtr StringPtrFromStrHandle(StringHandle strHandle)
  2171. {
  2172.     StringPtr result = kODNULL;
  2173.  
  2174.     if ( strHandle )
  2175.     {
  2176.         ODULong size = GetHandleSize((Handle) strHandle);
  2177.         StringPtr strPtr = (StringPtr) ODLockHandle((ODHandle) strHandle);
  2178.         result = (StringPtr) ODNewPtr(size);
  2179.         ODBlockMove(strPtr, result, size);
  2180.         ODUnlockHandle((ODHandle) strHandle);
  2181.     }
  2182.  
  2183.     return result;
  2184. }
  2185.  
  2186. //------------------------------------------------------------------------------
  2187. // DefaultMenuStringForKind
  2188. //------------------------------------------------------------------------------
  2189.  
  2190. ODStatic StringPtr DefaultMenuStringForKind()
  2191. {
  2192.     CUsingLibraryResources r;
  2193.  
  2194.     StringPtr result = kODNULL;
  2195.  
  2196.     StringHandle strHandle = GetString(kODPartInfoStrUnknownID);
  2197.     if ( strHandle )
  2198.     {
  2199.         result = StringPtrFromStrHandle(strHandle);
  2200.         ReleaseResource((Handle) strHandle);
  2201.     }
  2202.     else
  2203.     {
  2204.         strHandle = NewString("\p");
  2205.         result = StringPtrFromStrHandle(strHandle);
  2206.         ODDisposeHandle((ODHandle) strHandle);
  2207.     }
  2208.     return result;
  2209. }
  2210.  
  2211. //------------------------------------------------------------------------------
  2212. // GetMenuStringForKind
  2213. //------------------------------------------------------------------------------
  2214.  
  2215. ODStatic void GetMenuStringForKind(
  2216.     ODSession*        session,
  2217.     ODType            kind,
  2218.     StringPtr*        itemString,
  2219.     ODScriptCode*    itemScript)
  2220. {
  2221.     ODName*                name;
  2222.     Environment*        ev = somGetGlobalEnvironment();
  2223.     ODNameSpaceManager*    nsm = session->GetNameSpaceManager(ev);
  2224.  
  2225.     if ( GetUserKindFromKind(nsm, kind, &name) )
  2226.     {
  2227.         TempODName tempName = name; // DMc: ensure it's deleted
  2228.         *itemString = (StringPtr) ODNewPtr(GetITextStringLength(name)+1);
  2229.         IntlToPStr(name, *itemString);
  2230.         *itemScript = GetITextScriptCode(name);
  2231.     }
  2232.     else
  2233.     {
  2234.         // No available editors support this kind
  2235.         ODTranslation* translation = session->GetTranslation(ev);
  2236.         ODPlatformType platformType = translation->GetPlatformTypeFromISOType(ev, kind);
  2237.         if ( platformType != kODNULL )
  2238.         {
  2239.             *itemString = (StringPtr) ODNewPtr(sizeof(ODPlatformType) + 1);
  2240.             ODBlockMove(&platformType, &((*itemString)[1]), (ODULong) sizeof(ODPlatformType));
  2241.             (*itemString)[0] = (unsigned char) sizeof(ODPlatformType);
  2242.         }
  2243.         else
  2244.         {
  2245.             *itemString = DefaultMenuStringForKind();
  2246.         }
  2247.         *itemScript = smSystemScript;
  2248.     }
  2249. }
  2250.  
  2251. //------------------------------------------------------------------------------
  2252. // AddTranslationKindToMenu
  2253. //------------------------------------------------------------------------------
  2254.  
  2255. void AddTranslationKindToMenu(
  2256.         ODType        kind, 
  2257.         MenuHandle    kindMenu,
  2258.         short        item,
  2259.         ODBoolean    insert,
  2260.         ODSession*    session)
  2261. {
  2262.     StringPtr itemString;
  2263.     ODScriptCode itemScript;
  2264.     
  2265.     GetMenuStringForKind(session, kind, &itemString, &itemScript);
  2266.     TempODString tempItemString = (char*) itemString; // DMc: ensure it's deleted
  2267.  
  2268.     if ( insert )
  2269.     {
  2270.         item = InsertMenuItemIgnoreMeta(kindMenu, itemString, item);
  2271.     }
  2272.     else
  2273.         SetMenuItemText(kindMenu, item, itemString);
  2274.     
  2275.     SetPopupItemScript(kindMenu, item, itemScript);
  2276. }
  2277.  
  2278. //------------------------------------------------------------------------------
  2279. // GetTypeListItem 
  2280. //------------------------------------------------------------------------------
  2281.  
  2282. ODType GetTypeListItem(ODTypeList* typeList, ODUShort index)
  2283. {
  2284.     Environment* ev = somGetGlobalEnvironment();
  2285.     ODType theType = kODNULL;
  2286.  
  2287.     if ( index > 0 )
  2288.     {
  2289.         ODTypeListIterator* typeIter = typeList->CreateTypeListIterator(ev);
  2290.     
  2291.         for (theType = typeIter->First(ev);
  2292.              (typeIter->IsNotComplete(ev)) && (index > 1);
  2293.              theType = typeIter->Next(ev), --index)
  2294.         {
  2295.             ODDisposePtr(theType);
  2296.         }
  2297.     
  2298.         delete typeIter;
  2299.     }
  2300.     
  2301.     return theType;
  2302. }
  2303.  
  2304.